#include "StdAfx.h"
//#ifndef MAC_OS

//#endif

#include "GLESLib.h"
#if USEGLESVER_2
extern "C" void printShaderInfoLog(GLuint obj);
extern "C" void printProgramInfoLog(GLuint obj);
#endif

GLESLib::GLESLib(bool complex_mode, int viewport_orientation, int device_width, int device_height)
{
	printf("create opengl width:%d height:%d complexmode:%d angle:%d\n",device_width,device_height,complex_mode,viewport_orientation);
	_complex_mode = complex_mode;
	_viewport_orientation = viewport_orientation;
	_nColor2D			=	0;
	//m_nCrt2DTex			=	-1;
	_nNum2DQuads		=	0;
	//_device_orientation =	ORIENTATION_DEFAULT;
	
	//Init 2D rendering related data
	_pVtxBuffer2D		=	NULL;
	_pClrBuffer2D		=	NULL;
	_pTexBuffer2D		=	NULL;
	_pFlags				=	NULL;
	
#ifdef USE_FREE_TRANSFORM
	_pModBuffer2D		=	NULL;
#endif
	
#ifdef USE_GL_ROTATE
	_pRotateParams		= 	NULL;
	_is_rotate = false;
#endif
#ifdef USE_TRANSLATE
	_pTranslateParams = NULL;
	_is_translate = false;
#endif
#ifdef USE_GL_SCALE
	_pScaleParams		= 	NULL;
	_is_scale = false;
#endif

#ifdef ENABLE_OPACITY_SETTING
	_opacity_percent = 100;
#endif
	_device_width = device_width;
	_device_height = device_height;
}

GLESLib::~GLESLib()
{
	SAFE_DEL_ARRAY( _pVtxBuffer2D );
	SAFE_DEL_ARRAY( _pClrBuffer2D );
	SAFE_DEL_ARRAY( _pTexBuffer2D );
	SAFE_DEL_ARRAY( _pTexID );
	SAFE_DEL_ARRAY( _pIndices );
	SAFE_DEL_ARRAY( _pFlags );
	
#ifdef USE_FREE_TRANSFORM
	SAFE_DEL_ARRAY( _pModBuffer2D );	
#endif

#ifdef USE_GL_ROTATE
	SAFE_DEL_ARRAY(_pRotateParams);
#endif
#ifdef USE_TRANSLATE
	SAFE_DEL_ARRAY(_pTranslateParams);
#endif
#ifdef USE_GL_SCALE
	SAFE_DEL_ARRAY(_pScaleParams);
#endif
	
#ifdef USE_DRAW_LINE
	SAFE_DEL_ARRAY( _pLineIndices );
#endif
#ifdef USE_DRAW_CIRCLE
	SAFE_DEL_ARRAY (_pCircleIndices);
#endif //USE_DRAW_CIRCLE
#ifdef USE_DRAW_TRIANGLE_TRIP
	SAFE_DEL_ARRAY (_pTriangleTripIndices);
#endif
	
}

void GLESLib::SetClip(int x, int y, int w, int h)
{	
	if (_nNum2DQuads >= (MAX_2D_QUADS - 1))
	{
		return;
	}

	VXTUNIT*	pVtx	=	_pVtxBuffer2D + (VTX_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);

	//UINT8*	pClr	=	_pClrBuffer2D + (COLOR_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);
	//float*  pTex	=   _pTexBuffer2D + (TEXCOOR_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);

	_pTexID[_nNum2DQuads] = 0;
	_pFlags[_nNum2DQuads] = SETCLIP_FLAG;
	
	*pVtx++	=	x;		*pVtx++	=	y;
	*pVtx++	=	w+1;	*pVtx++	=	h+1;

	_nNum2DQuads++;
}

void GLESLib::ClearClip()
{
	if (_nNum2DQuads >= (MAX_2D_QUADS - 1))
	{
		return;
	}
	
	_pTexID[_nNum2DQuads] = 0;
	_pFlags[_nNum2DQuads] = CLEARCLIP_FLAG;
	
	_nNum2DQuads++;
}

void GLESLib::Clip(int x, int y, int w, int h)
{
	/*x = 5;
	y = 10;
	w = 50;
	h = 100;*/
	
	if(_complex_mode){
		if(_viewport_orientation == ORIENTATION_LANDSCAPE_270){
			int tmp = y;
			y = _device_height - x - w;
			x = _device_width - tmp - h;
		
			tmp = w;
			w = h;
			h = tmp;
		}else{
			int tmp = x;
			x = y;
			y = tmp;
			tmp = w;
			w = h;
			h = tmp;
		}
	}else{
		y = _device_height - y - h;
	}
	x *= _viewport_scalew;
	y *= _viewport_scaleh;
	w *= _viewport_scalew;
	h *= _viewport_scaleh;
	::glScissor(x, y, w, h);
}
void GLESLib::SetViewPort(int width, int height)
{
    printf("set view port\n");
	_viewport_scalew = (float)width/(float)_device_width;
	_viewport_scaleh = (float)height/(float)_device_height;
	::glViewport(0, 0, width, height);
}

void GLESLib::FillRect(GUNIT x, GUNIT y, GUNIT w, GUNIT h, bool enableAlpha)
{	
	if (_nNum2DQuads >= (MAX_2D_QUADS - 1))
	{
		Flush2D();
		//return;
	}

	VXTUNIT*	pVtx	=	_pVtxBuffer2D + (VTX_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);
	UINT8*	pClr	=	_pClrBuffer2D + (COLOR_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);
	float*  pTex	=   _pTexBuffer2D + (TEXCOOR_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);

	
	UINT8	a	=	(UINT8)((_nColor2D >> 24) & 0xFF);
	UINT8	r	=	(_nColor2D >> 16) & 0xFF;
	UINT8	g	=	(_nColor2D >> 8) & 0xFF;
	UINT8	b	=	_nColor2D & 0xFF;

	_pTexID[_nNum2DQuads] = 0;
	
	_pFlags[_nNum2DQuads] = 0;
	if (enableAlpha)
	{
		_pFlags[_nNum2DQuads] = TRANSP_FLAG;
	}
	
#ifdef USE_GL_ROTATE
	if (_is_rotate)
	{
		_pFlags[_nNum2DQuads] |= ROTATE_FLAG;
		_pRotateParams[_nNum2DQuads*NUM_ROTATE_PARAMS] = _rotate_angle;
		_pRotateParams[_nNum2DQuads*NUM_ROTATE_PARAMS + 1] = _rotate_x;
		_pRotateParams[_nNum2DQuads*NUM_ROTATE_PARAMS + 2] = _rotate_y;
	}
#endif
#ifdef USE_TRANSLATE
	if(_is_translate)
	{
		_pFlags[_nNum2DQuads] |= TRANSLATE_FLAG;
		_pTranslateParams[_nNum2DQuads*NUM_TRANSLATE_PARAMS] = _translate_x;
		_pTranslateParams[_nNum2DQuads*NUM_TRANSLATE_PARAMS+1] = _translate_y;
	}
#endif
#ifdef USE_GL_SCALE
	if (_is_scale)
	{
		_pFlags[_nNum2DQuads] |= SCALE_FLAG;
		_pScaleParams[_nNum2DQuads*NUM_SCALE_PARAMS] = _scale_x;
		_pScaleParams[_nNum2DQuads*NUM_SCALE_PARAMS + 1] = _scale_y;
		_pScaleParams[_nNum2DQuads*NUM_SCALE_PARAMS + 2] = _scale_center_x;
		_pScaleParams[_nNum2DQuads*NUM_SCALE_PARAMS + 3] = _scale_center_y;
	}
#endif
#ifdef USE_GL_MULTI_BUFFER
    _pframe[_nNum2DQuads] = _curr_frame;
#endif
	*pVtx++	=	x;		*pVtx++	=	y;
	*pClr++	=	r;		*pClr++	=	g;	*pClr++	=	b;	*pClr++	=	a;
	*pTex++	=	0.0f;	*pTex++	=	0.0f;

	*pVtx++	=	(x + w);	*pVtx++	=	y;
	*pClr++	=	r;		*pClr++	=	g;	*pClr++	=	b;	*pClr++	=	a;
	*pTex++	=	0.0f;	*pTex++	=	0.0f;

	*pVtx++	=	(x + w);	*pVtx++	=	(y + h);
	*pClr++	=	r;		*pClr++	=	g;	*pClr++	=	b;	*pClr++	=	a;
	*pTex++	=	0.0f;	*pTex++	=	0.0f;

	*pVtx++	=	x;		*pVtx++	=	(y + h);
	*pClr++	=	r;		*pClr++	=	g;	*pClr++	=	b;	*pClr++	=	a;
	*pTex++	=	0.0f;	*pTex++	=	0.0f;

	_nNum2DQuads++;
}
#ifdef USE_DRAW_CIRCLE
void GLESLib::FillCircle(GUNIT x, GUNIT y, int radius, bool enableAlpha)
{
	/*if (_nNum2DQuads >= (MAX_2D_QUADS - 1))
	{
		Flush2D();
		//return;
	}*/
	int xx1 = x + (int)(0 * radius);
	int yy1 = y + (int)(1 * radius);
	for (int angle = 0; angle<= 360; angle+=(360/(VTX_COUNT_PER_CIRCLE-1)))
	{
		int xx = x + (int)(sin((double)angle*3.1416/180) * radius);
		int yy = y + (int)(cos((double)angle*3.1416/180) * radius);
		
		DrawTriangle(x, y, xx1, yy1, xx, yy, enableAlpha);
		xx1 = xx;
		yy1 = yy;
	}
}

void GLESLib::DrawCircle(GUNIT x, GUNIT y, int radius, bool enableAlpha){
	int xx1 = x + (int)(0 * radius);
	int yy1 = y + (int)(1 * radius);
	for (int angle = 0; angle<= 360; angle+=(360/(VTX_COUNT_PER_CIRCLE-1)))
	{
		int xx = x + (int)(sin((double)angle*3.1416/180) * radius);
		int yy = y + (int)(cos((double)angle*3.1416/180) * radius);
		
		DrawLine(xx1, yy1, xx, yy, enableAlpha);
		xx1 = xx;
		yy1 = yy;
	}
}
#endif //USE_DRAW_CIRCLE

#ifdef USE_DRAW_LINE
void GLESLib::DrawLine(GUNIT x1, GUNIT y1, GUNIT x2, GUNIT y2,  int color1, int color2)
{
	if (_nNum2DQuads >= (MAX_2D_QUADS - 1))
	{
		//LOG("OpenGL ES Lib: Reach limit polygon array !!! \n");
		
		//Flush2D();
		return;
	}
	VXTUNIT*	pVtx	=	_pVtxBuffer2D + (VTX_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);

	UINT8*	pClr	=	_pClrBuffer2D + (COLOR_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);
	float*  pTex	=   _pTexBuffer2D + (TEXCOOR_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);

	
	UINT8	a1	=	(UINT8)((color1 >> 24) & 0xFF);
	UINT8	r1	=	(color1 >> 16) & 0xFF;
	UINT8	g1	=	(color1 >> 8) & 0xFF;
	UINT8	b1	=	color1 & 0xFF;
	
	UINT8	a2	=	(UINT8)((color2 >> 24) & 0xFF);
	UINT8	r2	=	(color2 >> 16) & 0xFF;
	UINT8	g2	=	(color2 >> 8) & 0xFF;
	UINT8	b2	=	color2 & 0xFF;

	_pTexID[_nNum2DQuads] = 0;
	_pFlags[_nNum2DQuads] = DRAWLINE_FLAG;
	//if (enableAlpha)
	{
		_pFlags[_nNum2DQuads] |= TRANSP_FLAG;
	}
#ifdef USE_GL_ROTATE
	if (_is_rotate)
	{
		_pFlags[_nNum2DQuads] |= ROTATE_FLAG;
		_pRotateParams[_nNum2DQuads*NUM_ROTATE_PARAMS] = _rotate_angle;
		_pRotateParams[_nNum2DQuads*NUM_ROTATE_PARAMS + 1] = _rotate_x;
		_pRotateParams[_nNum2DQuads*NUM_ROTATE_PARAMS + 2] = _rotate_y;
	}
#endif
#ifdef USE_TRANSLATE
	if(_is_translate)
	{
		_pFlags[_nNum2DQuads] |= TRANSLATE_FLAG;
		_pTranslateParams[_nNum2DQuads*NUM_TRANSLATE_PARAMS] = _translate_x;
		_pTranslateParams[_nNum2DQuads*NUM_TRANSLATE_PARAMS+1] = _translate_y;
	}
#endif
#ifdef USE_GL_MULTI_BUFFER
    _pframe[_nNum2DQuads] = _curr_frame;
#endif
	*pVtx++	=	x1;		*pVtx++	=	y1;
	*pClr++	=	r1;		*pClr++	=	g1;	*pClr++	=	b1;	*pClr++	=	a1;
	*pTex++	=	0.0f;	*pTex++	=	0.0f;

	*pVtx++	=	x2;		*pVtx++	=	y2;
	*pClr++	=	r2;		*pClr++	=	g2;	*pClr++	=	b2;	*pClr++	=	a2;
	*pTex++	=	0.0f;	*pTex++	=	0.0f;

	_nNum2DQuads++;
}
void GLESLib::DrawLine(GUNIT x1, GUNIT y1, GUNIT x2, GUNIT y2, bool enableAlpha)
{
	if (_nNum2DQuads >= (MAX_2D_QUADS - 1))
	{
		//LOG("OpenGL ES Lib: Reach limit polygon array !!! \n");
		
		Flush2D();
		//return;
	}

	VXTUNIT*	pVtx	=	_pVtxBuffer2D + (VTX_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);

	UINT8*	pClr	=	_pClrBuffer2D + (COLOR_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);
	float*  pTex	=   _pTexBuffer2D + (TEXCOOR_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);

	
	UINT8	a	=	(UINT8)((_nColor2D >> 24) & 0xFF);
	UINT8	r	=	(_nColor2D >> 16) & 0xFF;
	UINT8	g	=	(_nColor2D >> 8) & 0xFF;
	UINT8	b	=	_nColor2D & 0xFF;
	
#ifdef ENABLE_OPACITY_SETTING
	if (enableAlpha)
	{
		a = a*_opacity_percent/100;
	}
	else
	{
		a = 255*_opacity_percent/100;
	}
#endif

	_pTexID[_nNum2DQuads] = 0;
	_pFlags[_nNum2DQuads] = DRAWLINE_FLAG;
	if (enableAlpha 
#ifdef ENABLE_OPACITY_SETTING
	|| _opacity_percent < 100
#endif
	)
	{
		_pFlags[_nNum2DQuads] |= TRANSP_FLAG;
	}
#ifdef USE_GL_ROTATE
	if (_is_rotate)
	{
		_pFlags[_nNum2DQuads] |= ROTATE_FLAG;
		_pRotateParams[_nNum2DQuads*NUM_ROTATE_PARAMS] = _rotate_angle;
		_pRotateParams[_nNum2DQuads*NUM_ROTATE_PARAMS + 1] = _rotate_x;
		_pRotateParams[_nNum2DQuads*NUM_ROTATE_PARAMS + 2] = _rotate_y;
	}
#endif
#ifdef USE_TRANSLATE
	if(_is_translate)
	{
		_pFlags[_nNum2DQuads] |= TRANSLATE_FLAG;
		_pTranslateParams[_nNum2DQuads*NUM_TRANSLATE_PARAMS] = _translate_x;
		_pTranslateParams[_nNum2DQuads*NUM_TRANSLATE_PARAMS+1] = _translate_y;
	}
#endif
#ifdef USE_GL_MULTI_BUFFER
    _pframe[_nNum2DQuads] = _curr_frame;
#endif
	*pVtx++	=	x1;		*pVtx++	=	y1;
	*pClr++	=	r;		*pClr++	=	g;	*pClr++	=	b;	*pClr++	=	a;
	*pTex++	=	0.0f;	*pTex++	=	0.0f;

	*pVtx++	=	x2;		*pVtx++	=	y2;
	*pClr++	=	r;		*pClr++	=	g;	*pClr++	=	b;	*pClr++	=	a;
	*pTex++	=	0.0f;	*pTex++	=	0.0f;

	_nNum2DQuads++;
}
// ricky.nguyen add
void GLESLib::DrawRect(GUNIT x, GUNIT y, GUNIT w, GUNIT h, bool enableAlpha)
{
	DrawLine(x, y, x , y + h);
	DrawLine(x, y + h, x + w, y + h);
	DrawLine(x + w, y + h, x + w, y);
	DrawLine(x + w, y, x , y);
}
#endif

#ifdef USE_FREE_TRANSFORM
void GLESLib::LoadModel(float ox, float oy, float m11, float m12, float m21, float m22)
{
	if (_nNum2DQuads >= (MAX_2D_QUADS - 1))
	{
		//LOG("OpenGL ES Lib: Reach limit polygon array !!! \n");		
		//Flush2D();
		return;
	}
	_pFlags[_nNum2DQuads] |= FREE_TRANSFORM_FLAG;
	float*	pModel	=	_pModBuffer2D + (MODEL_SIZE * MODEL_COUNT_PER_QUAD * _nNum2DQuads);	
	*pModel++ = ox;
	*pModel++ = oy;
	*pModel++ = m11;
	*pModel++ = m12;
	*pModel++ = m21;
	*pModel++ = m22;
}
#endif
void GLESLib::CleanCurrentFlag()
{
	_pFlags[_nNum2DQuads] = 0;
}

void GLESLib::Draw2DTexture(GUNIT x, GUNIT y, int w, int h, UINT32 texId, float uv[], int flags, bool enableAlpha)
{
	if (_nNum2DQuads >= (MAX_2D_QUADS - 1))
	{
		//LOG("OpenGL ES Lib: Reach limit polygon array !!! \n");
		
		Flush2D();
		return;
	}

	VXTUNIT*	pVtx	=	_pVtxBuffer2D + (VTX_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);
	UINT8*	pClr	=	_pClrBuffer2D + (COLOR_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);
	float*	pTex	=   _pTexBuffer2D + (TEXCOOR_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);

	_pTexID[_nNum2DQuads] = texId;
	_pFlags[_nNum2DQuads] = 0;
	
	if (enableAlpha)
	{
		_pFlags[_nNum2DQuads] |= TRANSP_FLAG;
	}

#ifdef USE_GL_ROTATE
	if (_is_rotate)
	{
		_pFlags[_nNum2DQuads] |= ROTATE_FLAG;
		_pRotateParams[_nNum2DQuads*NUM_ROTATE_PARAMS] = _rotate_angle;
		_pRotateParams[_nNum2DQuads*NUM_ROTATE_PARAMS + 1] = _rotate_x;
		_pRotateParams[_nNum2DQuads*NUM_ROTATE_PARAMS + 2] = _rotate_y;
	}
#endif
#ifdef USE_TRANSLATE
	if(_is_translate)
	{
		_pFlags[_nNum2DQuads] |= TRANSLATE_FLAG;
		_pTranslateParams[_nNum2DQuads*NUM_TRANSLATE_PARAMS] = _translate_x;
		_pTranslateParams[_nNum2DQuads*NUM_TRANSLATE_PARAMS+1] = _translate_y;
	}
#endif
#ifdef USE_GL_SCALE
	if (_is_scale)
	{
		_pFlags[_nNum2DQuads] |= SCALE_FLAG;
		_pScaleParams[_nNum2DQuads*NUM_SCALE_PARAMS] = _scale_x;
		_pScaleParams[_nNum2DQuads*NUM_SCALE_PARAMS + 1] = _scale_y;
		_pScaleParams[_nNum2DQuads*NUM_SCALE_PARAMS + 2] = _scale_center_x;
		_pScaleParams[_nNum2DQuads*NUM_SCALE_PARAMS + 3] = _scale_center_y;
	}
#endif
#ifdef USE_GL_MULTI_BUFFER
	_pframe[_nNum2DQuads] = _curr_frame;
#endif
#ifdef ENABLE_OPACITY_SETTING
	int alpha_val = 255*_opacity_percent/100;
#else
	int alpha_val = 0xFF;
#endif
	//uv  (u0 v0)  (u1 v1)
	*pVtx++	=	x;		*pVtx++	=	y;
	*pClr++	=	0xFF;	*pClr++	=	0xFF;	*pClr++	=	0xFF;	*pClr++	=	alpha_val;
	*pTex++	=	uv[0];	*pTex++	=	uv[1]; //u0 v0
	

	*pVtx++	=	x + w;	*pVtx++	=	y;
	*pClr++	=	0xFF;	*pClr++	=	0xFF;	*pClr++	=	0xFF;	*pClr++	=	alpha_val;
	*pTex++	=	uv[2];	*pTex++	=	uv[1]; //u1 v0

	*pVtx++	=	x + w;	*pVtx++	=	y + h;
	*pClr++	=	0xFF;	*pClr++	=	0xFF;	*pClr++	=	0xFF;	*pClr++	=	alpha_val;
	*pTex++	=	uv[2];	*pTex++	=	uv[3];  //u1 v1

	*pVtx++	=	x;		*pVtx++	=	y + h;
	*pClr++	=	0xFF;	*pClr++	=	0xFF;	*pClr++	=	0xFF;	*pClr++	=	alpha_val;
	*pTex++	=	uv[0];	*pTex++	=	uv[3]; //u0 v1

	_nNum2DQuads++;
}

void GLESLib::ConfigOpenGL()
{
    printf("config open gl");
#if USEGLESVER_2
    GLbyte vShaderStr[] =
            "attribute highp vec4  a_position;                                 \n"
            "attribute highp vec4  a_color;                                    \n"
            "attribute vec2  a_texCoord;                                       \n"
            "varying   vec2  v_texCoord;                                       \n"
            "varying   vec4  v_color;                                          \n"
            "uniform mediump mat4  ModelViewMatrix;                            \n"
            "uniform float u_istexture;\n"
            "varying float v_istexture;\n"
            "void main()                                                       \n"
            "{                                                                 \n"
            "   v_istexture = u_istexture;\n"
            "   v_texCoord = a_texCoord;                                       \n"
            "   v_color = a_color*0.00392;\n"
            "   gl_Position = ModelViewMatrix * a_position;  \n"
            "}                                                                 \n";

    GLbyte fShaderStr[] =
            "precision mediump float;                            \n"
            "varying float v_istexture;\n"
            "varying vec2 v_texCoord;                                          \n"
            "varying vec4 v_color;                                             \n"
            "uniform sampler2D s_texture;                                      \n"
            "void main()                                                       \n"
            "{                                                                 \n"
            "if(v_istexture>0.0){\n"
            "   gl_FragColor = v_color*texture2D( s_texture, v_texCoord );             \n"
            "}else{\n"
            "   gl_FragColor = v_color; \n"
            "}\n"
            "}                                                                 \n";
    EXLOG("step 1");
    // Load the vertex/fragment shaders
    GLuint vertexShader = LoadShader((const char*)vShaderStr,GL_VERTEX_SHADER);
    GLuint fragmentShader = LoadShader((const char*)fShaderStr,GL_FRAGMENT_SHADER);
    // Create the program object
    _glprograme = glCreateProgram();
    if(_glprograme == 0){
        return;
    }
    glAttachShader(_glprograme, vertexShader);
    glAttachShader(_glprograme, fragmentShader);
    // Link the program
    glLinkProgram(_glprograme);
    // Check the link status
    GLint linked;
    glGetProgramiv(_glprograme, GL_LINK_STATUS, &linked);
    if(!linked)
    {
        printProgramInfoLog(_glprograme);
        glDeleteProgram(_glprograme);
        return;
    }
    EXLOG("step 2");
    // Get the attribute locations
    _positionLoc = glGetAttribLocation(_glprograme, "a_position");
    _texCoordLoc = glGetAttribLocation(_glprograme, "a_texCoord");
    _colorLoc    = glGetAttribLocation(_glprograme, "a_color");
    _istexLoc = glGetUniformLocation(_glprograme,"u_istexture");
    // Get the sampler location
    _samplerLoc = glGetUniformLocation ( _glprograme, "s_texture" );
    _modelViewMatrixLoc = glGetUniformLocation(_glprograme, "ModelViewMatrix");
    //_textureId = CreateSimpleTexture2D ();//*/
#ifdef USE_GL_MULTI_BUFFER
    EXLOG("step 3");
    GLbyte vShaderStrSimple[] =
            "attribute vec4 a_position;   \n"
            "attribute vec2 a_texCoord;   \n"
            "varying vec2 v_texCoord;     \n"
            "//uniform mat4  ProjectionModelMatrix;                           \n"
            "void main()                  \n"
            "{                            \n"
            "//   gl_Position = ProjectionModelMatrix*a_position; \n"
            "   gl_Position = a_position; \n"
            "   v_texCoord = a_texCoord;  \n"
            "}                            \n";

    GLbyte fShaderStrSimple[] =
            "precision mediump float;                            \n"
            "varying vec2 v_texCoord;                            \n"
            "uniform sampler2D s_texture;                        \n"
            "void main()                                         \n"
            "{                                                   \n"
            "  gl_FragColor = texture2D( s_texture, v_texCoord );\n"
            "}                                                   \n";
    EXLOG("step 4");
    GLuint vertexShaderSimple = LoadShader((const char*)vShaderStrSimple,GL_VERTEX_SHADER);
    GLuint fragmentShaderSimple = LoadShader((const char*)fShaderStrSimple,GL_FRAGMENT_SHADER);
    _glprograme2 = glCreateProgram();
    if(_glprograme2 == 0){
        EXLOG("_glprograme2 cannot be create");
        return;
    }
    glAttachShader(_glprograme2, vertexShaderSimple);
    glAttachShader(_glprograme2, fragmentShaderSimple);
    GLint linked2;
    glGetProgramiv(_glprograme2, GL_LINK_STATUS, &linked2);
    if(!linked2)
    {
        EXLOG("_glprograme2 cannot be link");
        printProgramInfoLog(_glprograme2);
        glDeleteProgram(_glprograme2);
        return;
    }
    _positionLoc2 = glGetAttribLocation(_glprograme2, "a_position");
    _texCoordLoc2 = glGetAttribLocation(_glprograme2, "a_texCoord");
    _samplerLoc2 = glGetUniformLocation ( _glprograme2, "s_texture" );
    //_projectionModelMatrixLoc = glGetUniformLocation(_glprograme2, "ProjectionModelMatrix");
    EXLOG("step 5");
#endif
#endif
	::glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	//set clear depth buffer value
#ifdef MAC_OS
	::glClearDepthf(1.0f);
#elif defined(QT_CREATOR) || defined(ANDROID_OS)
	::glClearDepthf(1.0f);
#else
	::glClearDepth(1);
#endif

	//enable z-buff
	::glDepthMask(GL_FALSE);	
	::glDisable(GL_DEPTH_TEST);
	//::glDepthMask(GL_TRUE);	
	//::glEnable(GL_DEPTH_TEST);
	//::glDepthFunc(GL_LEQUAL);
	
	//alpha test
#ifndef QT_CREATOR
	::glDisable(GL_ALPHA_TEST);
#endif
	//::glEnable(GL_ALPHA_TEST);
	//::glAlphaFunc(GL_GREATER, 0.0f);
	
	::glDisable(GL_CULL_FACE);
	//::glEnable(GL_CULL_FACE);
	//::glCullFace(GL_BACK);
	//::glFrontFace(GL_CCW);
	
	::glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	::glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
	::glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
	::glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
//#ifdef USE_DRAW_LINE
	//glEnable(GL_LINE_SMOOTH);
//#endif
#if USEGLESVER_1
	::glMatrixMode(GL_PROJECTION);						
	::glLoadIdentity();
#elif USEGLESVER_2
    _projectionMatrix.Identity();
    _modelorginalMatrix.Identity();
    if (_device_orientation == ORIENTATION_LANDSCAPE_270)
    {
#ifdef QT_CREATOR
        _projectionMatrix.Ortho(-(float)GAME_DESIGN_WIDTH,+0.0f,+0.0f,-(float)GAME_DESIGN_HEIGHT,-0.01f,+0.01f);
        _modelorginalMatrix = _modelorginalMatrix*_projectionMatrix;
#else

#endif
    }
    else
    {
#ifdef QT_CREATOR
        _projectionMatrix.Ortho(-(float)GAME_DESIGN_HEIGHT,+0.0f,+0.0f,-(float)GAME_DESIGN_WIDTH,-0.01f,+0.01f);
        _modelorginalMatrix = _modelorginalMatrix*_projectionMatrix;
        _modelorginalMatrix.Translate(0.0f,GAME_DESIGN_WIDTH,0.0f);
        _modelorginalMatrix.Rotate(-90.0f,0.0f,0.0f,1.0f);
#else
        _projectionMatrix.Ortho(-(float)GAME_DESIGN_WIDTH,+0.0f,-(float)GAME_DESIGN_HEIGHT,+0.0f,-0.01f,+0.01f);
        _modelorginalMatrix = _modelorginalMatrix*_projectionMatrix;
#endif
    }
#endif

#ifdef USE_GL_MULTI_BUFFER
    _projectionModelMatrix = _projectionMatrix * _modelorginalMatrix;
    glGenFramebuffers(GL_NUM_OF_BUFFER,&_frame_name[0]);
    glGenTextures(GL_NUM_OF_BUFFER,&_frame_texture[0]);
    glGenRenderbuffers(GL_NUM_OF_BUFFER,&_buffer_name[0]);
    for(int i = 0; i< GL_NUM_OF_BUFFER;i++){
        glBindFramebuffer(GL_FRAMEBUFFER,_frame_name[i]);
        glBindRenderbuffer(GL_RENDERBUFFER,_buffer_name[i]);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4,GAME_DESIGN_WIDTH,GAME_DESIGN_HEIGHT);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER,_buffer_name[i]);
        glBindTexture(GL_TEXTURE_2D,_frame_texture[i]);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,  GAME_DESIGN_WIDTH,GAME_DESIGN_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _frame_texture[i], 0);
    }
    glBindFramebuffer(GL_FRAMEBUFFER,0);
    //glBindRenderbuffer(GL_RENDERBUFFER,0);
#endif
}
void GLESLib::ShutdownGL(){
#if USEGLESVER_2
    glDeleteProgram(_glprograme);
#endif
}

void GLESLib::Flush2D()
{	
	glDisable(GL_SCISSOR_TEST);
	//::glClear(GL_COLOR_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
#if USEGLESVER_1
	::glMatrixMode(GL_PROJECTION);						
	::glLoadIdentity();
	GLORTHO(0, _device_width, _device_height, 0, -1.0f, 1.0f);
	if(_complex_mode){
		if(_viewport_orientation == ORIENTATION_LANDSCAPE_270){
			::glTranslatef(_device_width,0,0);
			::glRotatef(90.0f, 0.0f, 0.0f, 1.0f);
		}else{
			::glTranslatef(0,_device_height,0);
			::glRotatef(-90.0f, 0.0f, 0.0f, 1.0f);
		}
	}
	::glMatrixMode(GL_MODELVIEW);
	::glLoadIdentity();
#elif USEGLESVER_2
#endif
    if (_nNum2DQuads>0)
    {
#ifdef USE_GL_MULTI_BUFFER
        
        glUseProgram(0);
        UINT8 curr_frame = _pframe[0];
        glBindFramebuffer(GL_FRAMEBUFFER,0);
        if(curr_frame > -1){
            glBindFramebuffer(GL_FRAMEBUFFER,_frame_name[curr_frame]);
            //glBindRenderbuffer(GL_RENDERBUFFER,_buffer_name[curr_frame]);
        }else{
            glBindFramebuffer(GL_FRAMEBUFFER,0);
            //glBindRenderbuffer(GL_RENDERBUFFER,0);
        }
#endif
		//Render current 2D primitives		
#if USEGLESVER_1
		::glEnableClientState(GL_VERTEX_ARRAY);
		::glEnableClientState(GL_COLOR_ARRAY);	
		::glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		::glEnable(GL_TEXTURE_2D);
		
	#ifdef USE_FLOAT_VERTEX_POINTER
		::glVertexPointer(2, GL_FLOAT, 0, _pVtxBuffer2D);
	#else
		::glVertexPointer(2, GL_SHORT, 0, _pVtxBuffer2D);
	#endif
		::glColorPointer(4, GL_UNSIGNED_BYTE, 0, _pClrBuffer2D);		
		::glTexCoordPointer(2, GL_FLOAT, 0, _pTexBuffer2D);
		
#elif USEGLESVER_2
        glUseProgram(_glprograme);
        glVertexAttribPointer ( _positionLoc, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(GLfloat), _pVtxBuffer2D );
        glVertexAttribPointer ( _texCoordLoc, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(GLfloat), _pTexBuffer2D );
        glVertexAttribPointer ( _colorLoc, 4, GL_UNSIGNED_BYTE,GL_FALSE, 4 * sizeof(GLbyte), _pClrBuffer2D );
        // Bind the texture
#endif
		UINT32 current_flag = _pFlags[0];	
		UINT32 current_texture = _pTexID[0];
		INT32 texture_start_index = 0;
		INT32 total_element = 0;

		for (int i = 0; i <= _nNum2DQuads; i++)
		{
#ifdef USE_GL_MULTI_BUFFER
            
            curr_frame = _pframe[i];
            if(curr_frame > -1){
                glBindFramebuffer(GL_FRAMEBUFFER,_frame_name[curr_frame]);
                //glBindRenderbuffer(GL_RENDERBUFFER,_buffer_name[curr_frame]);
            }
			else
			{
                glBindFramebuffer(GL_FRAMEBUFFER,0);
                //glBindRenderbuffer(GL_RENDERBUFFER,0);
            }
            
#endif
			if (current_texture != _pTexID[i] || 
				current_flag != _pFlags[i] 
#ifdef USE_GL_ROTATE				
				|| ((current_flag & ROTATE_FLAG)!=0)
#endif
#ifdef USE_GL_SCALE				
				|| ((current_flag & SCALE_FLAG)!=0)
#endif
#ifdef USE_TRANSLATE
				|| ((current_flag & TRANSLATE_FLAG)!=0)
#endif
#ifdef USE_FREE_TRANSFORM
				|| ((current_flag & FREE_TRANSFORM_FLAG)!=0)
#endif
				)
			{
				if (current_flag&SETCLIP_FLAG)
				{
					::glEnable(GL_SCISSOR_TEST);
					int x = _pVtxBuffer2D[VTX_SIZE * VTX_COUNT_PER_QUAD * texture_start_index + 0];
					int y = _pVtxBuffer2D[VTX_SIZE * VTX_COUNT_PER_QUAD * texture_start_index + 1];
					int w = _pVtxBuffer2D[VTX_SIZE * VTX_COUNT_PER_QUAD * texture_start_index + 2];
					int h = _pVtxBuffer2D[VTX_SIZE * VTX_COUNT_PER_QUAD * texture_start_index + 3];
					
					Clip(x, y, w, h);
				}
				else if (current_flag&CLEARCLIP_FLAG)
				{
					::glDisable(GL_SCISSOR_TEST);
				}
				else
				{
                    if(current_texture>0)
                    {

#if USEGLESVER_1
                        glEnable(GL_TEXTURE_2D);
                        ::glBindTexture(GL_TEXTURE_2D, current_texture);
#elif USEGLESVER_2
                        glUniform1f ( _istexLoc, 1.0f );
                        glActiveTexture ( GL_TEXTURE0 );
                        glBindTexture(GL_TEXTURE_2D, current_texture);
                        glUniform1f ( _samplerLoc, 0.0f );
#endif
                    }
                    else
                    {
#if USEGLESVER_1
                        glDisable(GL_TEXTURE_2D);
#elif USEGLESVER_2
                        glUniform1f ( _istexLoc, 0.0f );
#endif
                    }
					if (current_flag&TRANSP_FLAG)
					{
						::glEnable (GL_BLEND);
						::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);			
					}
					else
					{
						::glDisable (GL_BLEND);
					}
				
#if USEGLESVER_1
					//if (current_flag & ROTATE_FLAG || current_flag & SCALE_FLAG)
					{
						::glPushMatrix();
						::glLoadIdentity();
					}
#elif USEGLESVER_2
                    _modelviewMatrix =  _modelorginalMatrix;
#endif
#ifdef USE_GL_ROTATE
					if (current_flag & ROTATE_FLAG)
					{
#if USEGLESVER_1
						::glTranslatef((_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 1]), (_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 2]), 0);
						::glRotatef(_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS], 0.0f, 0.0f, 1.0f);
						::glTranslatef(-(_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 1]), -(_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 2]), 0);
#elif USEGLESVER_2
                        _modelviewMatrix.Translate((_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 1]),(_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 2]), 0);
                        _modelviewMatrix.Rotate(_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS], 0.0f, 0.0f, 1.0f);
                        _modelviewMatrix.Translate(-(_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 1]), -(_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 2]), 0);
#endif
					}
#endif
#ifdef USE_TRANSLATE
					if(current_flag & TRANSLATE_FLAG)
					{
#if USEGLESVER_1
						::glTranslatef(_pTranslateParams[texture_start_index*NUM_TRANSLATE_PARAMS],_pTranslateParams[texture_start_index*NUM_TRANSLATE_PARAMS+1],0);
#elif USEGLESVER_2
                        _modelviewMatrix.Translate(_pTranslateParams[texture_start_index*NUM_TRANSLATE_PARAMS],_pTranslateParams[texture_start_index*NUM_TRANSLATE_PARAMS+1],0);
#endif
					}
#endif
#ifdef USE_GL_SCALE
					if (current_flag & SCALE_FLAG)
					{
#if USEGLESVER_1
						::glTranslatef( (_pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 2]),  (_pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 3]), 0);
						::glScalef(_pScaleParams[texture_start_index*NUM_SCALE_PARAMS], _pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 1], 1.0f);
						::glTranslatef(-(_pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 2]), -(_pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 3]), 0);
#elif USEGLESVER_2
                        _modelviewMatrix.Translate( (_pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 2]),  (_pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 3]), 0);
                        _modelviewMatrix.Scale(_pScaleParams[texture_start_index*NUM_SCALE_PARAMS], _pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 1], 1.0f);
                        _modelviewMatrix.Translate(-(_pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 2]), -(_pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 3]), 0);
#endif
					}
#endif
#ifdef USE_FREE_TRANSFORM
					if (current_flag & FREE_TRANSFORM_FLAG)
					{
						float*	pModel	=	_pModBuffer2D + (MODEL_SIZE * MODEL_COUNT_PER_QUAD * texture_start_index);	
						GLfloat model[] = 
							{
								*(pModel + 2), *(pModel + 3), 0.0f, 0.0f,
								*(pModel + 4), *(pModel + 5), 0.0f, 0.0f,
								0.0f         ,          0.0f, 1.0f, 0.0f,
								*(pModel + 0), *(pModel + 1), 0.0f, 1.0f								
							};
						::glMultMatrixf(model);
					}
#endif

					total_element = (i - texture_start_index);
#if USEGLESVER_1
#elif USEGLESVER_2
                    glEnableVertexAttribArray ( _positionLoc );
                    glEnableVertexAttribArray ( _texCoordLoc );
                    glEnableVertexAttribArray ( _colorLoc );
                    glUniformMatrix4fv(_modelViewMatrixLoc,1, GL_FALSE,_modelviewMatrix.data());
#endif
				
#ifdef USE_DRAW_LINE
					if (current_flag&DRAWLINE_FLAG)
					{
						::glDrawElements(GL_LINES, total_element * VTX_COUNT_PER_LINE, GL_UNSIGNED_SHORT, _pLineIndices + (texture_start_index * VTX_COUNT_PER_LINE));
					}
					else
#endif
#ifdef USE_DRAW_TRIANGLE
					if(current_flag&DRAWTRIANGLE_FLAG)
					{
						::glDrawElements(GL_TRIANGLES, total_element * VTX_COUNT_PER_TRIANGLE, GL_UNSIGNED_SHORT, _pTriangleIndices + (texture_start_index * VTX_COUNT_PER_TRIANGLE));
					}
					else
#endif
					{
						::glDrawElements(GL_TRIANGLES, total_element * TRI_COUNT_PER_QUAD * VTX_COUNT_PER_TRI, GL_UNSIGNED_SHORT, _pIndices + (texture_start_index * TRI_COUNT_PER_QUAD * VTX_COUNT_PER_TRI));
					}
					

#if USEGLESVER_1
					//if (current_flag & ROTATE_FLAG || current_flag & SCALE_FLAG)
					{
						::glPopMatrix();
					}
#elif USEGLESVER_2
                    glDisableVertexAttribArray ( _colorLoc );
                    glDisableVertexAttribArray ( _positionLoc );
                    glDisableVertexAttribArray ( _texCoordLoc );
#endif

				}
				
				current_flag = _pFlags[i];
				current_texture = _pTexID[i];
				texture_start_index = i;
			}	
		}

		//if not set clip, glDrawElements 
		if (current_flag&SETCLIP_FLAG)
		{
			::glEnable(GL_SCISSOR_TEST);
			int x = _pVtxBuffer2D[VTX_SIZE * VTX_COUNT_PER_QUAD * texture_start_index + 0];
			int y = _pVtxBuffer2D[VTX_SIZE * VTX_COUNT_PER_QUAD * texture_start_index + 1];
			int w = _pVtxBuffer2D[VTX_SIZE * VTX_COUNT_PER_QUAD * texture_start_index + 2];
			int h = _pVtxBuffer2D[VTX_SIZE * VTX_COUNT_PER_QUAD * texture_start_index + 3];
			
			Clip(x, y, w, h);
		}
		else if (current_flag&CLEARCLIP_FLAG)
		{
			::glDisable(GL_SCISSOR_TEST);
		}
		else
		{
            if(current_texture>0)
            {

#if USEGLESVER_1
                glEnable(GL_TEXTURE_2D);
                ::glBindTexture(GL_TEXTURE_2D, current_texture);
#elif USEGLESVER_2
                glUniform1f ( _istexLoc, 1.0f );
                glActiveTexture ( GL_TEXTURE0 );
                glBindTexture(GL_TEXTURE_2D, current_texture);
                glUniform1f ( _samplerLoc, 0.0f );
#endif
            }
            else
            {
#if USEGLESVER_1
                glDisable(GL_TEXTURE_2D);
#elif USEGLESVER_2
                glUniform1f ( _istexLoc, 0.0f );
#endif
            }
			if (current_flag&TRANSP_FLAG)
			{
				::glEnable (GL_BLEND);
				::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);			
			}
			else
			{
				::glDisable (GL_BLEND);
			}

#if USEGLESVER_1
			//if (current_flag & ROTATE_FLAG || current_flag & SCALE_FLAG)
			{
				::glPushMatrix();
				::glLoadIdentity();
			}
#elif USEGLESVER_2
            _modelviewMatrix =  _modelorginalMatrix;
#endif	
#ifdef USE_GL_ROTATE
			if (current_flag & ROTATE_FLAG)
			{
#if USEGLESVER_1
				::glTranslatef(_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 1], _pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 2], 0);
				::glRotatef(_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS], 0.0f, 0.0f, 1.0f);
				::glTranslatef(-(_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 1]), -(_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 2]), 0);
#elif USEGLESVER_2
                _modelviewMatrix.Translate((_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 1]), (_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 2]), 0);
                _modelviewMatrix.Rotate(_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS], 0.0f, 0.0f, 1.0f);
                _modelviewMatrix.Translate(-(_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 1]), -(_pRotateParams[texture_start_index*NUM_ROTATE_PARAMS + 2]), 0);
#endif
			}
#endif
#ifdef USE_TRANSLATE
			if(current_flag & TRANSLATE_FLAG)
			{
#if USEGLESVER_1
				::glTranslatef(_pTranslateParams[texture_start_index*NUM_TRANSLATE_PARAMS],_pTranslateParams[texture_start_index*NUM_TRANSLATE_PARAMS+1],0);
#elif USEGLESVER_2
                _modelviewMatrix.Translate(_pTranslateParams[texture_start_index*NUM_TRANSLATE_PARAMS],_pTranslateParams[texture_start_index*NUM_TRANSLATE_PARAMS+1],0);
#endif
			}
#endif

#ifdef USE_GL_SCALE
			if (current_flag & SCALE_FLAG)
			{
#if USEGLESVER_1
				::glTranslatef( (_pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 2]),  (_pRotateParams[texture_start_index*NUM_SCALE_PARAMS + 3]), 0);
				::glScalef(_pScaleParams[texture_start_index*NUM_SCALE_PARAMS], _pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 1], 1.0f);
				::glTranslatef(-(_pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 2]), -(_pRotateParams[texture_start_index*NUM_SCALE_PARAMS + 3]), 0);
#elif USEGLESVER_2
                _modelviewMatrix.Translate( (_pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 2]),  (_pRotateParams[texture_start_index*NUM_SCALE_PARAMS + 3]), 0);
                _modelviewMatrix.Scale(_pScaleParams[texture_start_index*NUM_SCALE_PARAMS], _pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 1], 1.0f);
                _modelviewMatrix.Translate(-(_pScaleParams[texture_start_index*NUM_SCALE_PARAMS + 2]), -(_pRotateParams[texture_start_index*NUM_SCALE_PARAMS + 3]), 0);
#endif
			}
#endif	
#ifdef USE_FREE_TRANSFORM
			if (current_flag & FREE_TRANSFORM_FLAG)
			{
				float*	pModel	=	_pModBuffer2D + (MODEL_SIZE * MODEL_COUNT_PER_QUAD * texture_start_index);	
				GLfloat model[] = 
					{
						*(pModel + 2), *(pModel + 3), 0.0f, 0.0f,
						*(pModel + 4), *(pModel + 5), 0.0f, 0.0f,
						0.0f         ,          0.0f, 1.0f, 0.0f,
						*(pModel + 0), *(pModel + 1), 0.0f, 1.0f
					};
				::glMultMatrixf(model);
			}
#endif



			total_element = _nNum2DQuads - texture_start_index;
#if USEGLESVER_1
#elif USEGLESVER_2
            glEnableVertexAttribArray ( _positionLoc );
            glEnableVertexAttribArray ( _texCoordLoc );
            glEnableVertexAttribArray ( _colorLoc );
            glUniformMatrix4fv(_modelViewMatrixLoc,1, GL_FALSE,_modelviewMatrix.data());
#endif
#ifdef USE_DRAW_LINE
			if (current_flag&DRAWLINE_FLAG)
			{
				::glDrawElements(GL_LINES, total_element * VTX_COUNT_PER_LINE, GL_UNSIGNED_SHORT, _pLineIndices + (texture_start_index * VTX_COUNT_PER_LINE));
			}
			else
			
#endif
#ifdef USE_DRAW_TRIANGLE
			if(current_flag&DRAWTRIANGLE_FLAG)
			{
				::glDrawElements(GL_TRIANGLES, total_element * VTX_COUNT_PER_TRIANGLE, GL_UNSIGNED_SHORT, _pTriangleIndices + (texture_start_index * VTX_COUNT_PER_TRIANGLE));
			}
			else
#endif
			{
				::glDrawElements(GL_TRIANGLES, total_element * TRI_COUNT_PER_QUAD * VTX_COUNT_PER_TRI, GL_UNSIGNED_SHORT, _pIndices + (texture_start_index * TRI_COUNT_PER_QUAD * VTX_COUNT_PER_TRI));
			}

#if USEGLESVER_1
			//if (current_flag & ROTATE_FLAG || current_flag & SCALE_FLAG)
			{
				::glPopMatrix();
			}
#elif USEGLESVER_2
            glDisableVertexAttribArray ( _colorLoc );
            glDisableVertexAttribArray ( _texCoordLoc );
            glDisableVertexAttribArray ( _positionLoc );
#endif
		}		
#if USEGLESVER_1
		::glDisableClientState(GL_TEXTURE_COORD_ARRAY);			
		::glDisableClientState(GL_COLOR_ARRAY);
		::glDisableClientState(GL_VERTEX_ARRAY);		
#elif USEGLESVER_2
        glUseProgram(0);
#endif
	}
	
	_nNum2DQuads = 0;
}

void GLESLib::ClearQuads()
{
	_nNum2DQuads = 0;
}

void GLESLib::Init()
{
	_pVtxBuffer2D = new VXTUNIT[MAX_2D_QUADS * VTX_SIZE * VTX_COUNT_PER_QUAD];
	_pClrBuffer2D = new UINT8[MAX_2D_QUADS * COLOR_SIZE * VTX_COUNT_PER_QUAD]; 
	_pTexBuffer2D = new float[MAX_2D_QUADS * TEXCOOR_SIZE * VTX_COUNT_PER_QUAD]; 
	_pTexID = new UINT32[MAX_2D_QUADS];
	_pIndices = new UINT16[MAX_2D_QUADS * TRI_COUNT_PER_QUAD * VTX_COUNT_PER_TRI]; //2 triangles per quad
	_pFlags = new UINT16[MAX_2D_QUADS];
	
#ifdef USE_FREE_TRANSFORM
	_pModBuffer2D = new float[MAX_2D_QUADS * MODEL_SIZE * MODEL_COUNT_PER_QUAD]; 
#endif
	
#ifdef USE_GL_ROTATE
	_pRotateParams = new float[MAX_2D_QUADS * NUM_ROTATE_PARAMS];
#endif
#ifdef USE_TRANSLATE
	_pTranslateParams = new float[MAX_2D_QUADS*NUM_TRANSLATE_PARAMS];
#endif
#ifdef USE_GL_SCALE
	_pScaleParams = new float[MAX_2D_QUADS * NUM_SCALE_PARAMS];
#endif
	
#ifdef USE_DRAW_LINE
	_pLineIndices = new UINT16[MAX_2D_QUADS * VTX_COUNT_PER_LINE];
#endif
#ifdef USE_DRAW_CIRCLE
	_pCircleIndices = new UINT16[MAX_2D_QUADS * VTX_COUNT_PER_CIRCLE];
#endif // USE_DRAW_CIRCLE
#ifdef USE_DRAW_TRIANGLE
	_pTriangleIndices = new UINT16[MAX_2D_QUADS * VTX_COUNT_PER_TRIANGLE];
#endif
	//create indices	
	for( int i = 0; i < MAX_2D_QUADS; i++ )
	{
		//first triangle
		_pIndices[i * TRI_COUNT_PER_QUAD * VTX_COUNT_PER_TRI ] = i*VTX_COUNT_PER_QUAD + 0;
		_pIndices[i * TRI_COUNT_PER_QUAD * VTX_COUNT_PER_TRI + 1] = i*VTX_COUNT_PER_QUAD + 1;
		_pIndices[i * TRI_COUNT_PER_QUAD * VTX_COUNT_PER_TRI + 2] = i*VTX_COUNT_PER_QUAD + 2;
		
		//second triangle
		_pIndices[i * TRI_COUNT_PER_QUAD * VTX_COUNT_PER_TRI + 3] = i*VTX_COUNT_PER_QUAD + 0;
		_pIndices[i * TRI_COUNT_PER_QUAD * VTX_COUNT_PER_TRI + 4] = i*VTX_COUNT_PER_QUAD + 2;
		_pIndices[i * TRI_COUNT_PER_QUAD * VTX_COUNT_PER_TRI + 5] = i*VTX_COUNT_PER_QUAD + 3;
		
#ifdef USE_DRAW_LINE
		_pLineIndices[i * VTX_COUNT_PER_LINE + 0] = i*VTX_COUNT_PER_QUAD + 0;
		_pLineIndices[i * VTX_COUNT_PER_LINE + 1] = i*VTX_COUNT_PER_QUAD + 1;
#endif
#ifdef USE_DRAW_CIRCLE
		for (int j =0; j< VTX_COUNT_PER_CIRCLE; j++)
		{
			_pCircleIndices[i * VTX_COUNT_PER_CIRCLE + j] = i*VTX_COUNT_PER_QUAD + j;
		}
#endif //USE_DRAW_CIRCLE	
#ifdef USE_DRAW_TRIANGLE
		for(int j = 0; j< VTX_COUNT_PER_TRIANGLE; j++)
		{
			_pTriangleIndices[i* VTX_COUNT_PER_TRIANGLE + j] = i* VTX_COUNT_PER_QUAD + j;

		}
#endif
#ifdef USE_GL_MULTI_BUFFER
        _curr_frame = -1;
        _pframe = new UINT8[MAX_2D_QUADS];
#endif
	}
}

#ifdef USE_GL_ROTATE
void GLESLib::SetRotate(float angle, float x, float y)
{
	_is_rotate = true;
	_rotate_angle = angle;
	_rotate_x = x;
	_rotate_y = y;
}

void GLESLib::ClearRotate()
{
	_is_rotate = false;
}
#endif

#ifdef USE_TRANSLATE
void GLESLib::SetTranslate(float x, float y)
{
	_is_translate = true;
	_translate_x = x;
	_translate_y = y;
}
void GLESLib::ClearTranslate()
{
	_is_translate = false;
}
#endif

#ifdef USE_GL_SCALE
void GLESLib::SetScale(float scale_x, float scale_y, float center_x, float center_y)
{
	_is_scale = true;
	_scale_x = scale_x;
	_scale_y = scale_y;
	_scale_center_x = center_x;
	_scale_center_y = center_y;
}

void GLESLib::ClearScale()
{
	_is_scale = false;
	_scale_x = 0.0;
	_scale_y = 0.0;
	_scale_center_x = 0.0;
	_scale_center_y = 0.0;
}
#endif

#ifdef ENABLE_OPACITY_SETTING
void GLESLib::SetOpacity(int percent)
{
	if (percent < 0)
		percent = 0;
	if (percent > 100)
		percent = 100;
	_opacity_percent = percent;
}
#endif

#ifdef USE_DRAW_TRIANGLE
void GLESLib::DrawTriangle(GUNIT x1, GUNIT y1, GUNIT x2, GUNIT y2, GUNIT x3, GUNIT y3, bool enableAlpha)
{
	if (_nNum2DQuads >= (MAX_2D_QUADS - 1))
	{
//		LOG("OpenGL ES Lib: Reach limit polygon array !!! \n");
		
		Flush2D();
		//return;
	}

	VXTUNIT*	pVtx	=	_pVtxBuffer2D + (VTX_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);
	UINT8*	pClr	=	_pClrBuffer2D + (COLOR_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);
	float*  pTex	=   _pTexBuffer2D + (TEXCOOR_SIZE * VTX_COUNT_PER_QUAD * _nNum2DQuads);

	
	UINT8	a	=	(UINT8)((_nColor2D >> 24) & 0xFF);
	UINT8	r	=	(_nColor2D >> 16) & 0xFF;
	UINT8	g	=	(_nColor2D >> 8) & 0xFF;
	UINT8	b	=	_nColor2D & 0xFF;

	_pTexID[_nNum2DQuads] = 0;
	_pFlags[_nNum2DQuads] = DRAWTRIANGLE_FLAG;
	if (enableAlpha)
	{
		_pFlags[_nNum2DQuads] |= TRANSP_FLAG;
	}
/*
#ifdef USE_GL_ROTATE
	if (_is_rotate)
	{
		_pFlags[_nNum2DQuads] |= ROTATE_FLAG;
		_pRotateParams[_nNum2DQuads*NUM_ROTATE_PARAMS] = _rotate_angle;
		_pRotateParams[_nNum2DQuads*NUM_ROTATE_PARAMS + 1] = _rotate_x;
		_pRotateParams[_nNum2DQuads*NUM_ROTATE_PARAMS + 2] = _rotate_y;
	}
#endif
	
#ifdef USE_TRANSLATE
	if(_is_translate)
	{
		_pFlags[_nNum2DQuads] |= TRANSLATE_FLAG;
		_pTranslateParams[_nNum2DQuads*NUM_TRANSLATE_PARAMS] = _translate_x;
		_pTranslateParams[_nNum2DQuads*NUM_TRANSLATE_PARAMS+1] = _translate_y;
	}
#endif
*/
	*pVtx++	=	x1;		*pVtx++	=	y1;
	*pClr++	=	r;		*pClr++	=	g;	*pClr++	=	b;	*pClr++	=	a;
	*pTex++	=	0.0f;	*pTex++	=	0.0f;

	*pVtx++	=	x2;		*pVtx++	=	y2;
	*pClr++	=	r;		*pClr++	=	g;	*pClr++	=	b;	*pClr++	=	a;
	*pTex++	=	0.0f;	*pTex++	=	0.0f;

	*pVtx++	=	x3;		*pVtx++	=	y3;
	*pClr++	=	r;		*pClr++	=	g;	*pClr++	=	b;	*pClr++	=	a;
	*pTex++	=	0.0f;	*pTex++	=	0.0f;

	_nNum2DQuads++;
}
#endif
/**
  * Function on OpenGLES 2.0
  */
#if USEGLESVER_2
GLuint GLESLib::LoadShader(const char *shaderSrc, GLenum type)
{
    GLuint shader;
    GLint compiled;

    // Create the shader object
    shader = glCreateShader(type);
    if(shader == 0)
        return 0;
    // Load the shader source
    glShaderSource(shader, 1, &shaderSrc, NULL);

    // Compile the shader
    glCompileShader(shader);
    // Check the compile status
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
    if(!compiled)
    {
        printShaderInfoLog(shader);
        glDeleteShader(shader);
        return 0;
    }
    return shader;
}

extern "C" void printShaderInfoLog(GLuint obj)
{
    EXLOG("gl shader log");
    int infologLength = 0;
    int charsWritten  = 0;
    char *infoLog;

    glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength);

    if (infologLength > 0)
    {
        infoLog = (char *)malloc(infologLength);
        glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
        EXLOG(infoLog);
        free(infoLog);
    }
}

extern "C" void printProgramInfoLog(GLuint obj)
{
    EXLOG("gl programe log");
    int infologLength = 0;
    int charsWritten  = 0;
    char *infoLog;
    glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infologLength);
    if (infologLength > 0)
    {
        infoLog = (char *)malloc(infologLength);
        glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
        EXLOG(infoLog);
        free(infoLog);
    }
}
#endif
#ifdef USE_GL_MULTI_BUFFER
void GLESLib::bindFrame(int frame_id){
    _curr_frame = frame_id;
}
void GLESLib::unbindFrame(){
    _curr_frame = -1;
}
#endif
